package sketchpad.gui.control;

import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import sketchpad.business.databuffer.bufferpool.impl.BufferPoolServiceImpl;
import sketchpad.business.datacalc.calchelper.impl.CalcHelperServiceImpl;
import sketchpad.business.dataflow.serializeobj.SerializeObj;
import sketchpad.business.dataflow.serializeservice.impl.SerializeServiceImpl;
import sketchpad.constant.SketchPadColor;
import sketchpad.gui.component.ItemChipView;
import sketchpad.constant.Calculate;
import sketchpad.constant.Config;
import sketchpad.constant.Geometry;
import sketchpad.gui.drawinggraph.*;
import sketchpad.gui.drawinggraph.Random;
import sketchpad.gui.drawinggraph.node.Node;
import sketchpad.business.dataflow.serializeservice.SerializeService;

import java.io.File;
import java.util.*;
import java.util.logging.Logger;

//控制所有与画图相关的任务
public final class DrawControl {

    private Geometry currentState;//当前画什么图形
    private Map<Integer, DrawItem> drawItemMap;//全局所有图形
    private GraphicsContext gc;
    private int globalId;//全局ID
    private boolean isSelect;
    private boolean readyToMove;
    private List<Integer> selectedItemList;
    private Map<Integer, Group> groupMap;

    private CalcHelperServiceImpl calcHelperServiceImpl;
    private Stage stage;
    private BufferPoolServiceImpl bufferPoolServiceImpl;

    private DrawItem lastSelectBox;
    private ItemChipView chipView = new ItemChipView(null);//初始化避免编译错误，实际main初始化负责设置

    public DrawControl(GraphicsContext context, Stage primaryStage){
        currentState = Geometry.RECTANGLE;
        drawItemMap = new HashMap<>();
        groupMap = new HashMap<>();
        globalId = 0;
        gc = context;
        stage = primaryStage;
        calcHelperServiceImpl = new CalcHelperServiceImpl(this);
        bufferPoolServiceImpl = new BufferPoolServiceImpl(this);
        isSelect = false;
        readyToMove = false;
        selectedItemList = new LinkedList<>();
    }

    public DrawItem create(Node node){
        return ElementFactory.getInstance(this).create(currentState,node);
    }

    public synchronized void draw(int itemId, Node mouseNode, boolean isSelf){
        if(!drawItemMap.containsKey(itemId))return;
        DrawItem item = drawItemMap.get(itemId);
        if (selectedItemList.contains(itemId)){
            item.setSelect(true);
        }
        item.setUpdate(true);
        if (!isSelf && item.getGeometryClass()==Geometry.RANDOM)((Random)item).getNodeList().add(mouseNode);
        item.draw(mouseNode,gc);
        item.setSelect(false);
        gc.setStroke(Color.valueOf(SketchPadColor.COLOR_SELECTED));
        if (!isSelf && item.getGeometryClass() != Geometry.RANDOM)drawAllItem();
    }

    public void drawAllItem(){
        clear();
        DrawItem selectBox = drawItemMap.get(Config.SELECT_ID);
        if (selectBox!=null){
            draw(selectBox.getId(), selectBox.getRightDownNode(),true);
        }
        List<DrawItem> itemList = new ArrayList<>(drawItemMap.values());
        for (int i = itemList.size()-1; i >= 0; i--){
            DrawItem item = itemList.get(i);
            if (item.getId()==Config.SELECT_ID)continue;
            draw(item.getId(), item.getRightDownNode(),true);
        }
        try {
            chipView.addItem();
        } catch (Exception e) {
            Logger.getLogger(e.getLocalizedMessage());
        }
    }

    public void clearScreen(){
        clear();
        drawItemMap.clear();
        selectedItemList.clear();
        try {
            chipView.addItem();
        } catch (Exception e) { Logger.getLogger(e.getLocalizedMessage());}
    }

    private void clear(){
        gc.clearRect(0,0,Config.WINDOW_LENGTH, Config.WINDOW_WIDTH);
    }

    public void openFile(File file){
        SerializeService service = new SerializeServiceImpl();
        SerializeObj serializeObj = service.deserialize(file);
        this.drawItemMap = serializeObj.getDrawItemMap();
        this.globalId = serializeObj.getGlobalId();
        this.groupMap = serializeObj.getGroupMap();
        drawAllItem();
    }

    public void storeFile(File file){
        SerializeService service = new SerializeServiceImpl();
        SerializeObj serializeObj = new SerializeObj.Builder().drawItem(drawItemMap).globalId(globalId).groupMap(groupMap).build();
        service.serialize(serializeObj, file);
    }

    //根据鼠标坐标画长方形选择框，返回所有顶点在选择框中的图形
    public void multiSelect(){
        if (lastSelectBox==null)return;
        Rectangle selectBox = (Rectangle)lastSelectBox;
        selectedItemList = calcHelperServiceImpl.multiSelect(selectBox.getLeftUpNode(),selectBox.getRightDownNode());
        readyToMove=!selectedItemList.isEmpty();
        //加入同一组对象所有成员
        Node minCorNode = new Node(Config.WINDOW_LENGTH, Config.WINDOW_WIDTH);
        Node maxCorNode = new Node(0,0);
        calcHelperServiceImpl.addGroupMemberAfterSelect(minCorNode,maxCorNode);
        //直接修改选择框数据，需要包含
        minCorNode.x = minCorNode.x - Calculate.SELECT_MARGIN >= 0 ? minCorNode.x - Calculate.SELECT_MARGIN : 0;
        minCorNode.y = minCorNode.y - Calculate.SELECT_MARGIN >= 0 ? minCorNode.y - Calculate.SELECT_MARGIN : 0;
        maxCorNode.x = maxCorNode.x + Calculate.SELECT_MARGIN <= Config.WINDOW_LENGTH ? maxCorNode.x + Calculate.SELECT_MARGIN : Config.WINDOW_LENGTH;
        maxCorNode.y = maxCorNode.y + Calculate.SELECT_MARGIN <= Config.WINDOW_WIDTH ? maxCorNode.y + Calculate.SELECT_MARGIN : Config.WINDOW_WIDTH;//扩大选择框
        lastSelectBox.setLeftUpNode(minCorNode);
        lastSelectBox.setRightDownNode(maxCorNode);
    }


    //**********Getter And Setter*************//

    public void setSelect(boolean select) {
        isSelect = select;
    }

    public boolean getIsSelect(){
        return isSelect;
    }

    public Map<Integer, DrawItem> getDrawItemMap() {
        return drawItemMap;
    }

    public void setCurrentState(Geometry currentState) {
        this.currentState = currentState;
    }

    public boolean isSelect() {
        return isSelect;
    }

    public List<Integer> getSelectedItemList() {
        return selectedItemList;
    }

    public void setSelectedItemList(List<Integer> selectedItemList) {
        this.selectedItemList = selectedItemList;
    }

    public Map<Integer, Group> getGroupMap() {
        return groupMap;
    }

    public int getGlobalId() {
        return globalId++;
    }

    public Stage getStage() {
        return stage;
    }

    public CalcHelperServiceImpl getCalcHelperServiceImpl() {
        return calcHelperServiceImpl;
    }

    public boolean isReadyToMove() {
        return readyToMove;
    }

    public void setReadyToMove(boolean readyToMove) {
        this.readyToMove = readyToMove;
    }

    public BufferPoolServiceImpl getBufferPoolServiceImpl() {
        return bufferPoolServiceImpl;
    }

    public DrawItem getLastSelectBox() {
        return lastSelectBox;
    }

    public void setLastSelectBox(DrawItem lastSelectBox) {
        this.lastSelectBox = lastSelectBox;
    }

    public void setChipView(ItemChipView chipView) {
        this.chipView = chipView;
    }
}
